#include "../../LIB/prpsock/prpsock.h"
#include "../../LIB/sspsock/sspsock.h"
#include "../GatewayLoginManager/LightLoginmanager.h"

using namespace BAM;

//#define SLEEPING

int main(int argc, char **argv)
{
	

	//UserInfo *ui = new UserInfo();
	//strcpy(ui->email, "petya@gmail.com");
	//strcpy(ui->id, "2");
	//ui->online = '1';
	////strcpy(ui->password, "12345678");
	//hash2(2, ui->password);
	//ui->registered = '1';

	//char *c = new char[sizeof UserInfo];
	//int len = ui->CopyToBuffer(c);
	//
	//char a[100];
	//
	//lm.AddRawRecord("petya", 5, c, len);
	////delete c;


if (argc != 5)
   {
	   cout << "USAGE: " << endl<<
		       "		Listener.exe localaddress:port relayaddress:port username password"<< endl
			   << "		Listener.exe port relayaddress:port username password" 
			<< endl << endl;
	   return 0;
   }

char *b = argv[1];

BAM::cIPAddr *ip = 0;
do
{
	if (*b == ':')
	{
		ip = new BAM::cIPAddr(argv[1]);
		break;
	}
}
while(*b++);

if (!ip)
{
	if (strlen(argv[1])>5)
	{
		cout << "wrong port\n";
		return -1;
	}
	char buf[15];
	memcpy(buf, "127.0.0.1:", 10);
	memcpy(buf+10, argv[1], strlen(argv[1])+1);
	ip = new BAM::cIPAddr(buf);
	
}





WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);

SOCKET ListenSocket;
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) 
{
	printf("Error at socket(): %ld\n", WSAGetLastError());
	WSACleanup();
	return -1;
}


sockaddr_in service;
service = ip->SockAddr();

if (bind( ListenSocket,(SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
{
	printf("bind() failed.\n");
    closesocket(ListenSocket);
	WSACleanup();
    return -1;
}

if (listen( ListenSocket, 1 ) == SOCKET_ERROR)
{
	printf("Error listening on socket.\n");
	WSACleanup();
	return -1;
}

SOCKET AcceptSocket;


	while(1) 
	{
		AcceptSocket = SOCKET_ERROR;
		while( AcceptSocket == SOCKET_ERROR ) 
		{
			AcceptSocket = accept( ListenSocket, NULL, NULL );
		}
		printf("Client connected.\n");
		break;
	}
	unsigned long one = 1;
	ioctlsocket(AcceptSocket, FIONBIO, &one);

	BAM::cPrpSocket *Forw;
	BAM::cSSPSocket *SSP;

	LightLoginManager lm(argv[3], argv[4]);

	try
	{
		Forw =  new BAM::cPrpSocket(0, &lm, BAM::cPacket((BAM::byte*)argv[3], strlen(argv[3])), lm.GetId(), BAM::Prp_Socket_Client);

		SSP = new BAM::cSSPSocket(Forw, &lm, BAM::cPacket((BAM::byte*)argv[3], strlen(argv[3])));
		
		SSP->connect(argv[2]); 
		

	}
	catch(...)

	{
		cout << "Couldn't connect to " << argv[2] << endl;
		
		#ifdef SLEEPING
		Sleep(10000);
		#endif

		return -1;
	}
	
	char buf[10000];
	cPacket p;
	int errc = 0;
	while(true)
	{
		try
		{
			
			Sleep(1);
			
			int res = ::recv(AcceptSocket, buf, 10000,0); /* *** */			
			//int res = LRecvWrapper(&AcceptSocket, ListenSocket, buf, 10000); 
			
			if ((res == -1) && (WSAGetLastError() != WSAEWOULDBLOCK) ) break;
			if (res == 0) break;
			
			if (res > 0) 
			{
				SSP->send(cPacket((BAM::byte*)buf, res)); /* *** */
				//if ( -1 == LSSPSendWrapper(SSP, &lm, "user", buf, res))
				//	break;
				//if (res == -1) break;
			}

			bool bres;

			bres = SSP->RecvEx(&p, false); /* *** */
			//res = LSSPRecvWrapper(SSP, &lm, "username", &p);
			//if (res == -1) break;
			if (bres)
			{
				res = ::send(AcceptSocket, (char*)(p.getData()), p.getLength(), 0); /* *** */
				//if (-1 == LSendWrapper(&AcceptSocket, ListenSocket, (char*)p.getData(), p.getLength()))
				//	break;
				if (res == -1) break;
			}
		}
		
		catch(const BAM::SocketException &e)
		{
			
			cout << "exception thrown:" << e.what();
			#ifdef SLEEPING
			Sleep(10000);
			#endif

			WSACleanup();
			return 0;

			break;	
		}

	}
	
	cout << "Connection closed with error " << WSAGetLastError() << endl;
	
	#ifdef SLEEPING
	Sleep(10000);
	#endif

	WSACleanup();
	return 0;
}